// adodb_impl.h
#ifndef BSLIB_DB_ADODB_IMPL_H_
#define BSLIB_DB_ADODB_IMPL_H_

#include "adodb.h"
#include <vector>
#include <sqltypes.h>

class ADODB::Impl
{
public:
	Impl();
	~Impl();

	bool Connect(const wchar_t* ip, const wchar_t* db, const wchar_t* user, const wchar_t* password, unsigned long timeout = 0);
	bool Connect(const wchar_t* connection_string, unsigned long timeout = 0);
	bool Disconnect();

	bool SetCommand(CommandType type, const wchar_t* sql);
	bool SetParameter(_bstr_t column, ParameterDirection direction, DataType type, void* buffer, std::size_t buffer_size);
	bool ExecuteCommand(HRESULT& hr, unsigned long timeout);
	
	bool GetRowCount(unsigned long& count);
	bool GetRowSize(std::size_t& size);
	bool GetColumnCount(short& count);

	bool GetColumnType(_variant_t column, DataType& type);
	bool GetColumnActualSize(_variant_t column, std::size_t& size);
	bool GetColumnDefinedSize(_variant_t column, std::size_t& size);
	bool GetColumnData(_variant_t column, DataType type, void* buffer, std::size_t buffer_size, int* actual_size);
			
	bool IsRowEmpty();
	bool MoveNextRow();
	
private:
	class OutputParameter
	{
	public:
		template<typename Column>
		OutputParameter(Column column, DataType type, void* buffer, std::size_t buffer_size)
			: column_(column) , type_(type), buffer_(buffer), buffer_size_(buffer_size)	{}

		const _variant_t& column() const { return column_; }
		DataType type() const { return type_; }
		void* buffer() const { return buffer_; }
		std::size_t buffer_size() const { return buffer_size_; }
		
	private:
		_variant_t column_;
		DataType type_;
		void* buffer_;
		std::size_t buffer_size_;
	};

	void ReleaseCommand();
	bool GetParameterData(_variant_t column, DataType type, void* buffer, std::size_t buffer_size, int* actual_size);
	bool GetVariantData(_variant_t& variant, void* buffer, std::size_t buffer_size, int* actual_size);
		
	bool com_init_;
	_Connection* connection_;
	_Command* command_;
	CommandTypeEnum command_type_;
	_Parameter* parameter_;
	_Recordset* recordset_;
	Parameters* parameters_;
	Fields* fields_;
	Field* field_;
	typedef std::vector<OutputParameter*> OUTPUT_PARAMETERS;
	OUTPUT_PARAMETERS output_parameters_;
	TIMESTAMP_STRUCT timestamp_;
};

#endif // BSLIB_DB_ADODB_IMPL_H_